package com.gs.netty.support.server;

import com.gs.netty.core.factory.NettyThreadFactory;
import com.gs.netty.support.properties.BaseNettyConfig;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;

import javax.net.ssl.SSLContext;
import java.util.concurrent.atomic.AtomicBoolean;
@Slf4j
public abstract class AbstractServer implements Server, CommandLineRunner,Runnable{

    private SSLContext sslContext;
    private String serverName;
    // 系统名称
    public static final String OS_NAME = System.getProperty("os.name");
    protected final AtomicBoolean started = new AtomicBoolean(false);
    protected final AtomicBoolean closed = new AtomicBoolean(false);
    private static boolean isLinuxPlatform = false;
    private static boolean isWindowsPlatform = false;
    private boolean isUseEpollNativeSelector = false;

    private int workerGroupThreads=1;

    private Thread thread;

    private BaseNettyConfig  baseNettyConfig;

    static {
        if (OS_NAME != null && OS_NAME.toLowerCase().contains("linux")) {
            isLinuxPlatform = true;
        }

        if (OS_NAME != null && OS_NAME.toLowerCase().contains("windows")) {
            isWindowsPlatform = true;
        }
    }

    protected SSLContext getSslContext() {
        return sslContext;
    }


    protected boolean isOpenSsl() {
        return sslContext!=null;
    }

    public <T extends BaseNettyConfig> T getBaseNettyConfig(Class<T> configClass) {
        return (T) baseNettyConfig;
    }

    public AbstractServer(BaseNettyConfig nettyConfig) throws Exception {
        this.baseNettyConfig = nettyConfig;
        this.serverName = this.getClass().getSimpleName();
        this.sslContext = nettyConfig.createSSLContext();
        if (workerGroupThreads > 1) {
            this.workerGroupThreads =nettyConfig.getWorkerGroupThreads();
        }
        this.isUseEpollNativeSelector = nettyConfig.isUseEpollNativeSelector();
    }



    protected boolean isLinuxPlatform() {
        return isLinuxPlatform;
    }

    protected boolean useEpoll() {
        return isLinuxPlatform()
                && isUseEpollNativeSelector
                && Epoll.isAvailable();
    }
    protected EventLoopGroup buildWorkerEventLoopGroupSelector(){
        if (useEpoll()) {
            if (workerGroupThreads >1) {
                return new EpollEventLoopGroup(workerGroupThreads,
                        NettyThreadFactory.webSocketThreadFactory(serverName+"EPOLLSelector_"));
            }
            return new EpollEventLoopGroup(NettyThreadFactory.webSocketThreadFactory(serverName+"EPOLLSelector_"));
        }else {
            if (workerGroupThreads >1) {
                return new NioEventLoopGroup(workerGroupThreads,
                        NettyThreadFactory.webSocketThreadFactory(serverName+"NIOSelector_"));
            }
            return new NioEventLoopGroup(NettyThreadFactory.webSocketThreadFactory(serverName+"NIOSelector_"));
        }

    }

    protected EventLoopGroup  buildBossEventLoopGroupSelector(){
        if (useEpoll()) {
            return new EpollEventLoopGroup(1, NettyThreadFactory.webSocketThreadFactory(serverName+"EPOLLBoss_"));
        }else {
            return new NioEventLoopGroup(1,NettyThreadFactory.webSocketThreadFactory(serverName+"NIOBoss_"));
        }

    }


    @Override
    public final void run() {
        start();
    }

    @Override
    public final void run(String... args) throws Exception {
        if (!started.compareAndSet(false, true)) {
            return;
        }
        this.thread = new Thread(this,serverName);
        // 启动线程
        this.thread.start();
    }


}
